home *** CD-ROM | disk | FTP | other *** search
- Chapter 15
-
-
-
-
-
- Sound Effects
- 286 Fastgraph User's Guide
-
-
- Overview
-
- In the realm of the IBM PC and PS/2 family of systems, a sound is
- defined by its frequency, duration, and volume. The frequency of a sound is
- measured in units called Hertz. While the PC and PS/2 can produce sounds
- ranging from 18 to more than one million Hertz, the average human can hear
- sounds between 20 and about 20,000 Hertz. The length of a sound, called its
- duration, is expressed in clock ticks; there are either 18.2 of 72.8 clock
- ticks per second, depending on the method used to produce the sound.
- Finally, the volume determines the loudness of the sound. As we'll see in
- this chapter, we can control a sound's volume only on the PCjr and Tandy 1000
- systems.
-
- Fastgraph contains several different methods for producing sound
- effects. These include single tones, a series of tones expressed
- numerically, or a series of tones expressed as musical notes. The sound
- effects may be discrete, continuous, or performed at the same time as other
- activity. The sound-related routines are independent of the other parts of
- Fastgraph and do not require any initialization routines be called.
-
-
- Sound Sources
-
- All members of the PC and PS/2 families can produce sounds using the
- 8253-5 programmable timer chip and the internal speaker. This method is
- limited to producing single sounds of given frequencies and durations,
- although we can combine these sounds to create interesting audio effects or
- play music. When we use this technique, we have no control over the sound
- volume. In fact, sound volumes often vary slightly on different systems
- because the physical properties of the speaker and its housing are not always
- the same.
-
- The PCjr and Tandy 1000 systems have an additional, more powerful chip
- for producing sounds. This is the Texas Instruments SN76496A sound chip,
- called the TI sound chip for short. The TI sound chip has three independent
- voice channels for producing pure tones, and a fourth channel for generating
- periodic or white noise. Each voice channel has a separate volume control
- that allows us to control the loudness of the sound it emits.
-
-
- Synchronous Sound
-
- A sound effect is said to be synchronous if it is produced while no
- other activity is being performed. In other words, a program makes a
- synchronous sound by starting the sound, waiting for a specified duration,
- and then stopping the sound. The program must wait for the sound to complete
- before doing anything else. As long as the duration is relatively short, the
- fact that the sound is synchronous has little or no effect on the program's
- execution speed. Fastgraph includes routines for producing synchronous sound
- using either the 8253-5 programmable timer or the TI sound chip.
-
- The fg_sound routine uses the programmable timer to produce a sound of a
- given frequency and duration. The frequency, defined by the first argument,
- is expressed in Hertz and must be an integer value between 18 and 32,767.
- The second argument defines the duration and is expressed in clock ticks;
- Chapter 15: Sound Effects 287
-
- there are 18.2 clock ticks per second. If the duration is zero or negative,
- the sound will continue until it is stopped with the fg_quiet routine.
-
- Example 15-1 uses the fg_sound routine to create different sound
- effects, pausing for one second between each. It first produces three
- distinct sounds of 20, 100, and 1,000 Hertz. Each of these sounds lasts for
- approximately 1/6 of a second (three clock ticks). The program then makes a
- warbling noise by quickly alternating sounds of similar frequencies.
- Finally, the program creates a sliding tone of increasing frequencies between
- 100 and 500 Hertz. Each tone in this sequence lasts for two clock ticks, so
- it takes about 4.5 seconds to play the entire sequence. In all cases,
- example 15-1 displays an identifying message just before each sound.
-
- Example 15-1.
-
- #include <fastgraf.h>
- #include <stdio.h>
- void main(void);
-
- void main()
- {
- int freq;
-
- printf("20 Hz tone...\n");
- fg_sound(20,3);
- fg_waitfor(18);
-
- printf("100 Hz tone...\n");
- fg_sound(100,3);
- fg_waitfor(18);
-
- printf("1000 Hz tone...\n");
- fg_sound(1000,3);
- fg_waitfor(18);
-
- printf("warble...\n");
- fg_sound(400,1);
- fg_sound(410,1);
- fg_sound(400,1);
- fg_sound(410,1);
- fg_waitfor(18);
-
- printf("sliding tone from 100 to 500 Hz...\n");
- for (freq = 100; freq <= 500; freq+=10)
- fg_sound(freq,2);
- }
-
-
- The fg_voice routine is analogous to the fg_sound routine, but it uses
- the TI sound chip rather than the programmable timer to create sound. For
- this reason, the fg_voice routine can only be used on the PCjr or Tandy 1000
- systems. The TI sound chip allows us to control the volume of a sound, and
- it also offers four distinct voice channels. Thus, fg_voice requires two
- additional arguments besides frequency and duration to define the voice
- channel and sound volume.
- 288 Fastgraph User's Guide
- The first argument to fg_voice defines the voice channel, as shown
- below.
-
- value meaning
-
- 1 voice channel #1
- 2 voice channel #2
- 3 voice channel #3
- 4 voice channel #4, periodic noise
- 5 voice channel #4, white noise
-
- If we use voice channels 1, 2, or 3, the second argument defines the sound
- frequency in Hertz, between 18 and 32,767. If we use voice channel 4,
- however, the second argument instead is a value that represents a specific
- frequency, as shown in this table.
-
- value frequency
-
- 0 512 Hertz
- 1 1024 Hertz
- 2 2048 Hertz
-
- The third argument defines the sound volume. It must be between 0 and 15,
- where 0 is silent and 15 is loudest. The fourth argument defines the sound
- duration in clock ticks. As with the fg_sound routine, there are 18.2 clock
- ticks per second, and if the duration is zero or negative, the sound will
- continue until stopped with the fg_quiet routine.
-
- Example 15-2 uses the fg_voice routine to create different sound effects
- using the TI sound chip. As in example 15-1, there is a pause of one second
- between each. The program first calls the fg_testmode routine to be sure it
- is running on a PCjr or Tandy 1000 system (video mode 9 is only available on
- these systems). If so, the program uses voice channel #4 to produce a 2,048
- Hertz periodic noise, followed by white noise of the same frequency. Both
- sounds are emitted at the maximum volume level (15) and last for about 1/6 of
- a second each (three clock ticks). After these noises, example 15-2 produces
- a 500 Hertz tone of increasing volume. In all cases, the program displays an
- identifying message just before each sound.
-
- Example 15-2.
-
- #include <fastgraf.h>
- #include <stdio.h>
- #include <stdlib.h>
- void main(void);
-
- void main()
- {
- int volume;
-
- if (fg_testmode(9,0) == 0) {
- printf("This program requires a PCjr or ");
- printf("a Tandy 1000 system.\n");
- exit(1);
- }
-
- printf("2048 Hz periodic noise...\n");
- Chapter 15: Sound Effects 289
-
- fg_voice(4,2,15,3);
- fg_waitfor(18);
-
- printf("2048 Hz white noise...\n");
- fg_voice(5,2,15,3);
- fg_waitfor(18);
-
- printf("500 Hz tone of increasing volume...\n");
- for (volume = 1; volume <= 15; volume++) {
- fg_voice(1,500,volume,0);
- fg_waitfor(4);
- }
-
- fg_quiet();
- }
-
-
- Note how example 15-2 uses a duration of zero (continuous sound) and the
- fg_waitfor routine to specify the duration for each volume level the 500
- Hertz tone sequence. This causes the transition between changes in volume to
- blend better with each other. The fg_quiet routine, which stops continuous
- sound started with the fg_sound or fg_voice routines, ends the sound after
- the final volume level.
-
- The fg_sound and fg_voice routines each produce a single sound. We've
- seen how to combine sounds to produce sound effects, but still the individual
- sounds are defined numerically -- that is, by a certain frequency and
- duration. It is often easier to create sounds from musical notes, and for
- this reason Fastgraph includes a routine fg_music that produces such sounds.
- The fg_music routine uses the programmable timer to produce synchronous
- sound; it does not support the TI sound chip.
-
- The fg_music routine has a single argument called the music string,
- passed by reference as a byte array or character string. The music string is
- simply a variable-length sequence of music commands, followed by a dollar-
- sign ($) terminator. Music commands are summarized in the following table.
-
- command meaning
-
- A thru G Play the specified note in the current octave.
-
- # May be appended to a note character (A through G) to make that note
- sharp.
-
- . May be appended to a note character (A through G) or a sharp (#) to
- extend that note by half its normal length. Multiple dots may be
- used, and each will again extend the note by half as much as the
- previous extension.
-
- Ln Set the length of subsequent notes and pauses. The value of n is
- an integer between 1 and 64, where 1 indicates a whole note, 2 a
- half note, 4 a quarter note, and so forth. If no L command is
- present, L4 is assumed.
-
- On Set the octave for subsequent notes. The value of n may be an
- integer between 0 and 6 to set a specific octave. It also can be a
- 290 Fastgraph User's Guide
-
- plus (+) or minus (-) character to increment or decrement the
- current octave number. Octave 4 contains middle C, and if no O
- command is present, O4 is assumed.
-
- P Pause (rest) for the duration specified by the most recent L
- command.
-
- Sn Set the amount of silence between notes. The value of n is an
- integer between 0 and 2. If n is 0, each note plays for the full
- period set by the L command (music legato). If n is 1, each note
- plays for 7/8 the period set by the L command (music normal). If n
- is 2, each note plays for 3/4 the period set by the L command
- (music staccato). If no S command is present, S1 is assumed.
-
- Tn Set the tempo of the music (the number of quarter notes per
- minute). The value of n is an integer between 32 and 255. If no T
- command is present, T120 is assumed.
-
- The fg_music routine ignores any other characters in the music string. It
- also ignores command values outside the allowable range, such as T20 or O8.
-
- Example 15-3 illustrates some uses of the fg_music routine. The program
- plays the first few bars of "Mary Had a Little Lamb", followed by the musical
- scale (including sharps) in two octaves, and finally the introduction to
- Beethoven's Fifth Symphony. There is a pause of one second between each
- piece of music, and the program displays the titles before playing the music.
- Blank characters appear in the music strings to help make them more readable.
-
- Example 15-3.
-
- #include <fastgraf.h>
- #include <stdio.h>
- void main(void);
-
- void main()
- {
- printf("Mary Had a Little Lamb...\n");
- fg_music("T150 L8 EDCDEEE P DDD P EGG P EDCDEEE L16 P L8 EDDEDC$");
- fg_waitfor(18);
-
- printf("up the scale in two octaves...\n");
- fg_music("L16 CC#DD#EFF#GG#AA#B O+ CC#DD#EFF#GG#AA#B$");
- fg_waitfor(18);
-
- printf("Beethoven's Fifth Symphony...\n");
- fg_music("T180 O2 L2 P L8 P GGG L2 D# L24 P L8 P FFF L2 D$");
- }
-
-
- Asynchronous Sound
-
- Sounds made concurrently with other activity in a program are said to be
- asynchronous. Fastgraph's routines that produce asynchronous sound just
- start the sound and then immediately return control to the calling program.
- The sounds will automatically stop when the end of the sequence is reached,
- and you also can suspend or stop it on demand before that time. None of
- Chapter 15: Sound Effects 291
-
- Fastgraph's asynchronous sound routines have any effect if there is already
- asynchronous sound in progress. In addition, the asynchronous sound routines
- temporarily disable the synchronous sound routines (fg_sound, fg_voice, and
- fg_music) while asynchronous sound is in progress.
-
- To expand the range of sound effects and to play fast-tempo music,
- Fastgraph temporarily quadruples the clock tick interrupt rate from 18.2 to
- 72.8 ticks per second while producing asynchronous sound. Because many disk
- controllers rely on the 18.2 tick per second clock rate to synchronize disk
- accesses, your programs should not perform any disk operations when
- asynchronous sound is in progress.
-
- The fg_sounds routine is the asynchronous version of the fg_sound
- routine. It uses the programmable timer to play a sequence of tones
- simultaneous to other operations. This routine expects as its first argument
- a variable-length integer array, passed by reference, containing pairs of
- frequency and duration values. As with the fg_sound routine, each frequency
- is expressed in Hertz and must be between 18 and 32,767. The durations are
- also measured in clock ticks, but because the interrupt rate is quadrupled,
- there are 72.8 instead of 18.2 ticks per second.
-
- The format of the frequency and duration array passed to fg_sounds is
- shown below.
-
- [0] frequency of sound 1
-
- [1] duration of sound 1
-
- [2] frequency of sound 2
-
- [3] duration of sound 2
- .
- .
- .
- .
- .
- [2n-2] frequency of sound n
-
- [2n-1] duration of sound n
-
- [2n] terminator (0)
-
- Note that a null character (that is, a zero byte) terminates the array. The
- second argument passed to fg_sounds is an integer value indicating the number
- of times to cycle through the frequency and duration array. If this value is
- negative, the sounds will continue until stopped with the fg_hush or
- fg_hushnext routines.
-
- Example 15-4 uses the fg_sounds routine to play the 100 to 500 Hertz
- sliding tone sequence of example 15-1. To prove the sounds are being made
- concurrently with other operations, messages are displayed while the sequence
- is playing. This is controlled by the Fastgraph routine fg_playing, which
- returns a value of 1 if asynchronous sounds are in progress, and 0 if not.
- Note how the duration must be specified as 8 clock ticks (instead of 2 as in
- example 15-1) to compensate for the quadrupled clock tick interrupt rate.
- 292 Fastgraph User's Guide
-
- Example 15-4.
-
- #include <fastgraf.h>
- #include <stdio.h>
- void main(void);
-
- void main()
- {
- int i;
- int freq;
- int sound_array[83];
-
- i = 0;
-
- for (freq = 100; freq <= 500; freq+=10) {
- sound_array[i++] = freq;
- sound_array[i++] = 8;
- }
- sound_array[i] = 0;
-
- fg_sounds(sound_array,1);
-
- while(fg_playing())
- printf("Still playing...\n");
- }
-
-
- Just as the fg_sounds routine is analogous to the fg_sound routine,
- there is a Fastgraph routine fg_voices that is similar to the fg_voice
- routine. That is, fg_voices uses the TI sound chip to play an asynchronous
- sequence of tones. Its arguments are the same as those of the fg_sounds
- routine, but the structure of the sound array is different. Its structure
- is:
-
- [0] channel # of sound 1
-
- [1] frequency of sound 1
-
- [2] volume of sound 1
-
- [3] duration of sound 1
- .
- .
- .
- .
- .
- [4n-4] channel # of sound n
-
- [4n-3] frequency of sound n
-
- [4n-2] volume of sound n
-
- [4n-1] duration of sound n
-
- [4n] terminator (0)
-
- Chapter 15: Sound Effects 293
-
- The channel numbers, frequencies, volumes, and durations must be in the same
- ranges as discussed in the description of the fg_voice routine, except the
- durations are quadrupled because of the accelerated clock tick interrupt
- rate. Again, note that a null character (that is, a zero byte) terminates
- the array.
-
- Example 15-5 uses the fg_voices routine to play the 500 Hertz tone
- sequence of increasing volume introduced in example 15-2. As in example
- 15-4, the program displays messages while the tone sequence is playing to
- demonstrate the sounds are being made concurrently with other operations.
- Note how the duration is now 16 clock ticks (instead of 4 as in example 15-2)
- because of the quadrupled clock tick interrupt rate.
-
- Example 15-5.
-
- #include <fastgraf.h>
- #include <stdio.h>
- void main(void);
-
- void main()
- {
- int voice_array[61];
- int i;
- int volume;
-
- if (fg_testmode(9,0) == 0) {
- printf("This program requires a PCjr or ");
- printf("a Tandy 1000 system.\n");
- exit(1);
- }
-
- i = 0;
-
- for (volume = 1; volume <= 15; volume++) {
- voice_array[i++] = 1; /* use channel 1 */
- voice_array[i++] = 500; /* 500 Hz frequency */
- voice_array[i++] = volume; /* variable volume */
- voice_array[i++] = 16; /* duration */
- }
- voice_array[i] = 0;
-
- fg_voices(voice_array,1);
-
- while(fg_playing())
- printf("Still playing...\n");
- }
-
-
- There is also an asynchronous version of the fg_music routine. It is
- called fg_musicb, and it uses the same format music string as the fg_music
- routine does. However, the fg_musicb routine has a second argument that
- specifies the number of times to cycle through the music string. If this
- value is negative, the music will play repetitively until you stop it with
- the fg_hush or fg_hushnext routine.
- 294 Fastgraph User's Guide
- Example 15-6 plays the same three pieces of music as example 15-3, but
- it does so concurrently with other operations. As the music plays, the
- program continuously displays the title of each piece. Note how we can take
- advantage of the repetition in the music string for the "up the scale"
- sequence by playing the sequence twice.
-
- Example 15-6.
-
- #include <fastgraf.h>
- #include <stdio.h>
- void main(void);
-
- void main()
- {
- fg_musicb("T150 L8 EDCDEEE P DDD P EGG P EDCDEEE L16 P L8 EDDEDC$",1);
- while (fg_playing())
- printf("Mary Had a Little Lamb...\n");
- fg_waitfor(18);
-
- fg_musicb("L16 CC#DD#EFF#GG#AA#B O+$",2);
- while (fg_playing())
- printf("up the scale in two octaves...\n");
- fg_waitfor(18);
-
- fg_musicb("T180 O2 L2 P L8 P GGG L2 D# L24 P L8 P FFF L2 D$",1);
- while (fg_playing())
- printf("Beethoven's Fifth Symphony...\n");
- }
-
- The next example demonstrates the effects of the Fastgraph routines
- fg_hush and fg_hushnext, which stop sounds started with the fg_sounds,
- fg_voices, or fg_musicb routines. The fg_hush routine immediately stops
- asynchronous sound, whereas the fg_hushnext routine does so when the current
- cycle finishes. Neither routine has any arguments, and neither routine has
- any effect if no asynchronous sound is in progress. Furthermore, note that
- fg_hushnext has no effect unless the asynchronous sound is continuous.
-
- Example 15-7 runs in any text or graphics video mode. It displays
- rectangles in up to 16 colors while playing continuous asynchronous music.
- The program periodically checks for keystrokes with the fg_intkey routine,
- and it continues to play the music while there is no keyboard activity. If
- you press the Escape key, the program uses fg_hush to stop the music
- immediately; this causes an exit from the while loop. If you press any other
- key, the program uses fg_hushnext to stop the music as soon as the current
- repetition finishes. Once it does, the program exits the while loop because
- fg_playing will return a value of zero.
-
- Example 15-7.
-
- #include <fastgraf.h>
- void main(void);
-
- #define ESC 27
-
- void main()
- {
-
- Chapter 15: Sound Effects 295
- int color;
- int old_mode;
- unsigned char key, aux;
-
- old_mode = fg_getmode();
- fg_setmode(fg_automode());
- color = 0;
-
- fg_musicb("O4 L16 CC#DD#EFF#GG#AA#B O+ CC#DD#EFF#GG#AA#B$",-1);
-
- while (fg_playing())
- {
- color = (color + 1) & 15;
- fg_setcolor(color);
- fg_rect(0,fg_getmaxx(),0,fg_getmaxy());
-
- fg_waitfor(4);
- fg_intkey(&key,&aux);
- if (key == ESC)
- fg_hush();
- else if (key+aux != 0)
- fg_hushnext();
- }
-
- fg_setmode(old_mode);
- fg_reset();
- }
-
- Example 15-7 also demonstrates an important side-effect of the fg_musicb
- routine when playing continuous music. Any length, octave, silence, or tempo
- values changed within the string are not reset to their original values at
- the beginning of each repetition. If we did not include the O4 command at
- the beginning of the string, the later O+ command would cause the music to
- play in octaves 4 and 5 during the first repetition, 5 and 6 during the
- second repetition, and octave 6 for all subsequent repetitions (because you
- cannot increase the octave number above 6).
-
- The final two routines relating to asynchronous sound are fg_resume and
- fg_suspend. The fg_suspend routine suspends music previously started by
- fg_musicb, while fg_resume restarts the music from the point where it was
- suspended. Example 15-8 plays the first few bars of "Mary Had a Little
- Lamb". If you press any key while the song is playing, it stops. Then,
- after another keystroke, the music resumes and continues until finished.
-
- Example 15-8.
-
- #include <fastgraf.h>
- #include <stdio.h>
- void main(void);
-
- void main()
- {
- fg_musicb("T150 L8 EDCDEEE P DDD P EGG P EDCDEEE L16 P L8 EDDEDC$",1);
- fg_waitkey();
-
- fg_suspend();
-
- 296 Fastgraph User's Guide
-
- printf("Music suspended. Press any key to resume.\n");
- fg_waitkey();
-
- fg_resume();
- printf("Music resumed.\n");
- while (fg_playing());
- printf("Music finished.\n");
- }
-
-
- The fg_suspend routine has no effect if there is no asynchronous music in
- progress. Similarly, fg_resume has no effect if there is no suspended music.
- If you call fg_suspend and then need to cancel the music or exit to DOS
- instead of restarting the music, call fg_hush instead of fg_resume.
-
-
- Summary of Sound Routines
-
- This section summarizes the functional descriptions of the Fastgraph
- routines presented in this chapter. More detailed information about these
- routines, including their arguments and return values, may be found in the
- Fastgraph Reference Manual.
-
- FG_HUSH immediately stops asynchronous sound started with the fg_sounds,
- fg_voices, or fg_musicb routines.
-
- FG_HUSHNEXT is similar to fg_hush, but it does not stop the asynchronous
- sound until the current repetition finishes.
-
- FG_MUSIC uses the programmable timer to play a sequence of musical
- tones.
-
- FG_MUSICB is the asynchronous version of the fg_music routine. It uses
- the programmable timer to play a sequence of musical tones, concurrent with
- other activity.
-
- FG_PLAYING determines whether or not there is any asynchronous sound in
- progress.
-
- FG_QUIET stops continuous synchronous sound started with the fg_sound or
- fg_voice routines.
-
- FG_RESUME restarts asynchronous music previously suspended by
- fg_suspend.
-
- FG_SOUND produces a tone of a specified frequency and duration using the
- programmable timer.
-
- FG_SOUNDS is the asynchronous version of the fg_sound routine. It can
- play a series of tones of specified frequencies and durations, concurrent
- with other activity.
-
- FG_SUSPEND suspends asynchronous music previously started by fg_musicb.
-
- FG_VOICE produces a tone of a specified frequency, duration, and volume
- using one of the TI sound chip's four voice channels.
- Chapter 15: Sound Effects 297
-
- FG_VOICES is the asynchronous version of the fg_voice routine. It can
- play a series of tones of specified frequencies, durations, and volumes,
- concurrent with other activity.
- 298 Fastgraph User's Guide